package com.dji.compose_learning.ui.view

import android.util.Log
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.calculateTargetValue
import androidx.compose.animation.core.tween
import androidx.compose.animation.splineBasedDecay
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.gestures.horizontalDrag
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.positionChange
import androidx.compose.ui.input.pointer.util.VelocityTracker
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import com.dji.compose_learning.viewmodel.SampleListViewModel
import com.dji.compose_learning.utils.viewModel
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlin.math.absoluteValue
import kotlin.math.roundToInt

private fun Modifier.swipeToDismiss(onDismissListener: () -> Unit): Modifier {
    return composed {
        val offsetX = remember {
            Animatable(0f)
        }
        //速度计算
        val velocityTracker = VelocityTracker()
        //这里处理点击事件 按下、移动、抬起等等
        pointerInput(Unit) {
            val decay = splineBasedDecay<Float>(this) //衰减器，样条衰减
            coroutineScope {
                while (true) {
                    //等待触摸按下事件
                    val pointerId = awaitPointerEventScope {
                        awaitFirstDown().id //首次按下的事件id
                    }
                    awaitPointerEventScope {  //点击事件监测
                        horizontalDrag(pointerId) { changed ->  //横向拖动监测
                            val horizontalDragOffset =
                                offsetX.value + changed.positionChange().x //横向拖动的距离 拖动是个连续的行为需要累计到已拖动的距离
                            launch { //这里调用的是一个挂起方法
                                offsetX.snapTo(horizontalDragOffset) //将当前值变化到目标值 这里通过Animatable使值的变换成为一个连续的变换
                            }
                            velocityTracker.addPosition(changed.uptimeMillis,
                                changed.position) //记录位置和时间可以获取速度
//                            offsetT = horizontalDragOffset
                        }
                    }
                    val velocity = velocityTracker.calculateVelocity().x //获取速度
                    val targetOffsetX = decay.calculateTargetValue(offsetX.value, velocity)
                    //设置滑动的边界值
                    offsetX.updateBounds(lowerBound = -size.width.toFloat(),
                        upperBound = size.width.toFloat())
                    launch {
                        if (targetOffsetX.absoluteValue <= size.width) {
                            //复位
                            offsetX.animateTo(targetValue = 0f, initialVelocity = velocity)
                        } else {
                            //启动衰减动画
                            offsetX.animateDecay(velocity, decay)
                            onDismissListener()
                            //这里需要复位，列表刷新后modify没有重新刷新导致item内容刷新但是位置却不对
                            offsetX.animateTo(targetValue = 0f,
                                animationSpec = tween(durationMillis = 0))
                        }
                    }
                }
            }

        }.offset {
//            Log.i("offsetX","${offsetX.value.roundToInt()}")
            IntOffset(offsetX.value.roundToInt(), 0)
//            IntOffset(offsetT.roundToInt(), 0)
        }
    }
}

@Composable
fun GestureView() {
    val viewModel = viewModel<SampleListViewModel>()
    val dataList by viewModel.sampleList.observeAsState(listOf())
    Surface(modifier = Modifier.fillMaxSize()) {
        Column {
            Text(text = "手势动画")
            Spacer(modifier = Modifier.height(10.dp))
            LazyColumn(modifier = Modifier.fillMaxWidth()) {
                items(dataList.size) {
                    Text(text = "${dataList[it]}", modifier = Modifier
                        .swipeToDismiss {
                            viewModel.removeItem(dataList[it])
                        }
                        .background(MaterialTheme.colorScheme.primary)
                        .fillMaxWidth()
                        .padding(15.dp), color = MaterialTheme.colorScheme.onPrimary)
                }
            }
            Spacer(modifier = Modifier.height(10.dp))
            Text(text = "点击手势")
            Spacer(modifier = Modifier.height(10.dp))
            var number by rememberSaveable {
                mutableStateOf(0)
            }
            Row(verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.Center,
                modifier = Modifier.fillMaxWidth()) {
                Text(text = "$number",
                    textAlign = TextAlign.Center,
                    modifier = Modifier
                        .pointerInput(Unit) {
                            detectTapGestures(
                                onPress = { Log.i("onPress", "onPress") },
                                onDoubleTap = {
                                    Log.i("onDoubleTap", "onDoubleTap")
                                    number--
                                },
                                onLongPress = {
                                    Log.i("onLongPress", "onLongPress")
                                    number += 2
                                },
                                onTap = {
                                    Log.i("onTap", "onTap")
                                    number++
                                }
                            )
                        }
                        .wrapContentSize()
                        .background(MaterialTheme.colorScheme.primary)
                        .padding(40.dp),
                    color = MaterialTheme.colorScheme.onPrimary)
            }
        }
    }
}